/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief MaCI - Ranging Interface Server module header
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _MACI_RANGING_RANGINGSERVER_HPP_
#define _MACI_RANGING_RANGINGSERVER_HPP_
#include "MaCI.hpp"
#include "thread.hpp"
#include "sync.hpp"
#include "RangingData.hpp"
#include <vector>

namespace gimi {
  class GIMIMessage;
}

namespace MaCI {
  namespace Ranging {

    /** MaCI - RangingServer Interface.
     *
     * This class defines a Server module to be used with the 
     * MaCI Ranging interface.
     */
    class CRangingServer : public CMaCI, private gim::CSync, private gim::CThread
    {
    public:
      /** Constructor.
       * 
       * Constructor of the RangingServer. This requires;
       * a pointer to Initialized and connected GIMI, minor
       * number of this interface (Used as GIMI minor number)
       *
       * @param[in] aMaCICtrlServerPtr Pointer to GIMI used for communication
       * @param[in] aInterfaceMinor Interface minor number. Usually
       * used to indicate the instance of devices of same
       * type.
       * @param[in] aDescription User provided description about
       * service. This description will be appended after text
       * 'MaCI-RangingServer; ' in the GIMI service description
       * field.
       */
      CRangingServer(MaCICtrl::CMaCICtrlServer *aMaCICtrlServerPtr, 
                     const int aInterfaceMinor,
                     const std::string &aDescription = "");
 
      
      /** Destructor.
       *
       * Cleans up the class. Calls the Close() function to verify
       * that all derived-class things are closed.
       *
       */
      ~CRangingServer();
      
      
      /** Send a DistanceArray event.
       *
       * This function is used to send a DistanceArray to service
       * subscribers. DistanceArray data should be packed to
       * CRangingData container prior to sending. The BinBag inside
       * the CRangingData may contain any user-defined additional fields
       * if required.
       *
       * A valid DistanceArray event consists of minimum of three
       * entries in the CRangingData container:
       * 'TTimestamp'
       * 'TDistanceHeader'
       * 'TDistance' * n (where: n > 0 && n == distanceheader.beam_count)
       * 
       * For information on how to construct the CRangingData entry,
       * see the class CRangingData
       *
       * \see CRangingData
       *
       * @param[in] aData       CRangingData container containing
       *                        the DistanceArray data.
       * @return                true - Sending was succesfull
       *                        false - Sending failed.
       */
      bool SendDistanceArrayEvent(const CRangingData &aData);


      /** Set device limits.
       *
       * Sets the device limits to specified values. These values can then 
       * be used by the Client for adapting to current hardware.
       * 
       * @param[in] aMinDistance Minimum distance this device is capable of 
       *                         measuring (in meters)
       * @param[in] aMaxDistance Maximum distance this device is capable of
       *                         measuring (in meters)
       */
      void SetDeviceLimits(const float aMinDistance, const float aMaxDistance);
      
      
      /** Set device position.
       *
       * Sets the devices relative position. This information can be used by
       * the client to correctly align to any position dependent application. 
       * (like; visualization)
       *
       * @param[in] aX          Device position in X axis (in meters)        
       * @param[in] aY          Device position in Y axis (in meters)        
       * @param[in] aZ          Device position in X axis (in meters)
       * @param[in] aHeading    Device heading (in radians, zero is 
       *                        towards the X axis, and
       *                        positive values go counter-clockwise)
       */
      void SetDevicePosition(const float aX, const float aY, 
			     const float aZ, const float aHeading);


      /** Open device.
       *
       * Opens the device, basicly registers device to GIMI.
       *  
       * @return                Returns a value of type EMaCIError. 
       *                        
       * \see EMaCIError
       */
      EMaCIError DoOpen(void);


      /** Close device.
       *
       * Closes the device. Closes all GIMI registrations and queues.
       *
       * @return                Returns a value of type EMaCIError.
       *
       * \see EMaCIError
       */
      EMaCIError DoClose(void);

    protected:
    private:
      int ThreadFunction(int aThreadNumber); ///< Thread executing function
      int ProcessMessage(const gimi::GIMIMessage &msg); ///< Message processing function

    private:
      int iDistanceArrayEventSeq; ///< Current sequence number of received distancearrays
      int iMessageSeq; ///< Current messagesequence

      TDeviceInformationPosition iDevicePosition; ///< Device position.
      TDeviceInformationLimits iDeviceLimits; ///< Device limits.

      std::string iServiceDescription; ///< Service description.
    };
  }
}

#endif

